package com.jfshop.framework.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

public class TimeUtil {
	private static final String DEFUALT_TIME_PATTEN = "yyyy-MM-dd HH:mm:ss";

	/**
	 * @throws RuntimeException
	 */
	private TimeUtil() throws RuntimeException {
		throw new RuntimeException("util class is static");
	}

	/**
	 * 将long类型时间转化为字符串 （格式：yyyy-MM-dd mm:dd:ss）
	 * @param time              时间（毫秒）
	 * @param timeZone          所在时区
	 * @return                  字符串类型的时间
	 */
	public static String formatDate(long time) {
		final SimpleDateFormat format = new SimpleDateFormat(DEFUALT_TIME_PATTEN);
		format.setTimeZone(TimeZoneUtil.getTimeZone());
		return format.format(time);
	}

	/**
	 * 将long类型时间转化为字符串
	 * @param time                   时间（毫秒）
	 * @param pattern                输出格式，例："yyyy-MM-dd HH:mm:ss.SSS"
	 * @param timeZone               所在时区
	 * @return                       字符串类型的时间
	 */
	public static String formatDate(long time, String pattern, TimeZone timeZone) {
		final SimpleDateFormat format = new SimpleDateFormat(pattern);
		format.setTimeZone(timeZone);
		return format.format(time);
	}

	/**
	 * 得到long类型时间的年份
	 * @param time           时间（毫秒）
	 * @param timeZone       所在时区
	 * @return               年份
	 */
	public static int getYear(long time, TimeZone timeZone) {
		final Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(time);
		calendar.setTimeZone(timeZone);
		return calendar.get(Calendar.YEAR);
	}

	/**
	 * 得到long类型时间的月份（从1算起）
	 * @param time                    时间（毫秒）
	 * @param timeZone                所在时区
	 * @return                        月份（从1算起）
	 */
	public static int getMonth(long time, TimeZone timeZone) {
		final Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(time);
		calendar.setTimeZone(timeZone);
		return calendar.get(Calendar.MONTH) + 1;
	}

	/**
	 * 得到long类型时间的天（在月份里是第几天，从1算起）
	 * @param time                 时间（毫秒）
	 * @param timeZone             所在时区
	 * @return                     天（在月份里是第几天，从1算起）
	 */
	public static int getDayInMonth(long time, TimeZone timeZone) {
		final Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(time);
		calendar.setTimeZone(timeZone);
		return calendar.get(Calendar.DAY_OF_MONTH);
	}

	/**
	 * 得到long类型时间的天（在星期里是第几天，星期日=1、星期一=2 ...）
	 * @param time                    时间（毫秒）
	 * @param timeZone                所在时区
	 * @return                        天（在星期里是第几天，星期日=1 、星期一=2 ...）
	 */
	public static int getDayInWeek(long time, TimeZone timeZone) {
		final Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(time);
		calendar.setTimeZone(timeZone);
		return calendar.get(Calendar.DAY_OF_WEEK);
	}

	/**
	 * 得到long类型时间的天（在年里是第几天，从1算起）
	 * @param time             时间（毫秒）
	 * @param timeZone         所在时区
	 * @return                 年份
	 */
	public static int getDayInYear(long time, TimeZone timeZone) {
		final Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(time);
		calendar.setTimeZone(timeZone);
		return calendar.get(Calendar.DAY_OF_YEAR);
	}

	/**
	 * 得到long类型时间 所在的月份 最大的天数（例：8月=31）
	 * @param time                时间（毫秒）
	 * @param timeZone            所在时区
	 * @return                    最大的天数（例：8月=31）
	 */
	public static int getMaxDayInMonth(long time, TimeZone timeZone) {
		final Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(time);
		calendar.setTimeZone(timeZone);
		return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
	}

	/**
	 * time1 和 time2，相差的天数 （ time1 - time2 ）
	 * @param time1
	 * @param time2
	 * @return time1 和 time2，相差的天数 （ time1 - time2 ）
	 */
	public static long getDateDeffDay(long time1, long time2) {
		// (time1-time2)/(24*60*60*1000)
		return (time1 - time2) / 86400000;
	}

	/**
	 * time1 和 time2，相差的月数 （年份也计算在内，即相差一年 = 相差12个月）（ time1 - time2 ）
	 * @param time1
	 * @param time2
	 * @return time1 和 time2，相差的月数 （年份也计算在内，即相差一年 = 相差12个月）（ time1 - time2 ）
	 */
	public static long getDateDeffMonth(long time1, long time2) {
		final Calendar calendar1 = Calendar.getInstance();
		final Calendar calendar2 = Calendar.getInstance();

		calendar1.setTimeInMillis(time1);
		calendar2.setTimeInMillis(time2);

		return (calendar1.get(Calendar.YEAR) - calendar2.get(Calendar.YEAR))
				* 12 + calendar1.get(Calendar.MONTH)
				- calendar2.get(Calendar.MONTH);
	}

	/**
	 * 在 time 加上 minute 分钟
	 * @param time
	 * @param minute     可以为负数
	 * @return
	 */
	public static long addMinute(long time, int minute) {
		// time + 60*1000
		return time + 60000 * minute;
	}

	/**
	 * 在 time 加上 hour 小时
	 * 
	 * @param time
	 * @param hour    可以为负数
	 * @return
	 */
	public static long addHour(long time, int hour) {
		// time + 60*60*1000
		return time + 3600000 * hour;
	}

	/**
	 * 在 time 加上 day 天
	 * @param time
	 * @param day    可以为负数
	 * @return
	 */
	public static long addDay(long time, int day) {
		// time + 24*60*60*1000
		return time + 86400000 * day;
	}

	/**
	 * 在 time 加上 month 月（只改变月 和 年，其他不变；会出现7月31日 - 1个月 = 6月30日）
	 * @param time
	 * @param month      可以为负数
	 * @param timeZone
	 * @return
	 */
	public static long addMonth(long time, int month, TimeZone timeZone) {
		final Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(time);
		calendar.setTimeZone(timeZone);

		calendar.add(Calendar.MONTH, month);

		return calendar.getTimeInMillis();
	}

	/**
	 * 在 time 加上 year 年（只改变年，其他不变；会出现2012年2月29日 + 1年 = 2013年2月28日）
	 * @param time
	 * @param year             可以为负数
	 * @param timeZone
	 * @return
	 */
	public static long addYear(long time, int year, TimeZone timeZone) {

		final Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(time);
		calendar.setTimeZone(timeZone);

		calendar.add(Calendar.YEAR, year);

		return calendar.getTimeInMillis();
	}

	/**
	 * 根据输入的时间信息，得到相应的以毫秒为单位的 时间
	 * @param year             年
	 * @param month            月(1月 = 1)
	 * @param day              日
	 * @param hour             小时
	 * @param minute           分钟
	 * @param second           秒
	 * @param milliSecond      毫秒
	 * @param timeZone         时区
	 * @return                 以毫秒为单位的 时间
	 */
	public static long getTimeMillis(int year, int month, int day, int hour,
			int minute, int second, int milliSecond, TimeZone timeZone) {

		final Calendar calendar = Calendar.getInstance();
		calendar.setTimeZone(timeZone);

		calendar.set(Calendar.YEAR, year);
		calendar.set(Calendar.MONTH, month - 1);
		calendar.set(Calendar.DAY_OF_MONTH, day);
		calendar.set(Calendar.HOUR_OF_DAY, hour);
		calendar.set(Calendar.MINUTE, minute);
		calendar.set(Calendar.SECOND, second);
		calendar.set(Calendar.MILLISECOND, milliSecond);

		return calendar.getTimeInMillis();
	}

	/**
	 * 根据输入的时间信息（ 毫秒 = 0 )，得到相应的以毫秒为单位的 时间
	 * @param year             年
	 * @param month            月(1月 = 1)
	 * @param day              日
	 * @param hour             小时
	 * @param minute           分钟
	 * @param second           秒
	 * @param timeZone         时区
	 * @return                 以毫秒为单位的 时间
	 */
	public static long getTimeMillis(int year, int month, int day, int hour,
			int minute, int second, TimeZone timeZone) {
		return getTimeMillis(year, month, day, hour, minute, second, 0,
				timeZone);
	}

	/**
	 * 根据输入的时间信息（ 小时、分钟、秒、毫秒 = 0 )，得到相应的以毫秒为单位的 时间
	 * @param year            年
	 * @param month           月(1月 = 1)
	 * @param day             日
	 * @param timeZone        时区
	 * @return                以毫秒为单位的 时间
	 */
	public static long getTimeMillis(int year, int month, int day,
			TimeZone timeZone) {
		return getTimeMillis(year, month, day, 0, 0, 0, 0, timeZone);
	}

	/**
	 * 将字符串时间转换为Long类型时间
	 * @param dateStr
	 * @return 以毫秒为单位的时间
	 */
	public static Long formatDate(String dateStr) {
		if (dateStr == null || dateStr.length() == 0) {
			return null;
		}
		
		Date date = null;
		final SimpleDateFormat format = new SimpleDateFormat(DEFUALT_TIME_PATTEN);
		try {
			date = format.parse(dateStr);
		} catch (ParseException e) {
			throw new RuntimeException("字符串时间转换为Long类型出错：" + e.getMessage());
		}
		return date.getTime();
	}

	/**
	 * 获取当前的时间
	 * @return 以毫秒为单位
	 */
	public static Long getTimeNow() {
		return System.currentTimeMillis();
	}

	/**
	 * 获取上一天11:59:59时间
	 * @return
	 */
	public static String lastDay() {
		final String startTime = TimeUtil.specificTime(0,-1, 12, 0, 0);
		return startTime;
	}
	
	/**
	 * 获取上一天11:59:59时间(long类型)
	 * @return
	 */
	public static long lastDayLong() {
		return string2TimeLong(lastDay());
	}

	/**
	 * 获取当前的时间
	 * @return
	 */
	public static String currentDay() {
		final String endTime = TimeUtil.specificTime(0,0, 11, 59, 59);
		return endTime;
	}
	
	/**
	 * 获取当前的时间(long类型)
	 * @return
	 */
	public static long currentDayLong() {
		return string2TimeLong(currentDay());
	}
	
	/**
	 * 获取当前的日期和时间
	 * @return    返回当前的日期和时间
	 */
	public static String getDateAndTimeNow() {
		return new SimpleDateFormat(DEFUALT_TIME_PATTEN).format(new Date());
	}
	
	/**
	 * 获取指定时间
	 */
	public static String specificTime(int month,int day,int hour,int minute,int second) {
		final Calendar calendar = Calendar.getInstance();
		final GregorianCalendar g = new GregorianCalendar(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH)+month,
				calendar.get(Calendar.DAY_OF_MONTH)+day, hour, minute, second);
		String date = new SimpleDateFormat(DEFUALT_TIME_PATTEN).format(g.getTime());
		return date;
	}

	/**
	 * 上一个月的第一天和最后一天
	 * @return
	 */
	public static String[] lastMonth() {
		final Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.DAY_OF_MONTH, 1);
	
		final GregorianCalendar g = new GregorianCalendar(calendar.get(Calendar.YEAR), 
				calendar.get(Calendar.MONTH)-1,calendar.get(Calendar.DAY_OF_MONTH), 12,0, 0);
		String date = new SimpleDateFormat(DEFUALT_TIME_PATTEN).format(g.getTime());
		
		
		GregorianCalendar g2 = new GregorianCalendar(calendar.get(Calendar.YEAR), 
				calendar.get(Calendar.MONTH),calendar.get(Calendar.DAY_OF_MONTH), 11,59, 59);
		String date2 = new SimpleDateFormat(DEFUALT_TIME_PATTEN).format(g2.getTime());
		return new String[]{date,date2};
	}
	
	/**
	 * 本月的第一天和最后一天
	 * @return
	 */
	public static String[] currMonth() {
		final Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.DAY_OF_MONTH, 1);
	
		final GregorianCalendar g = new GregorianCalendar(calendar.get(Calendar.YEAR), 
				calendar.get(Calendar.MONTH),calendar.get(Calendar.DAY_OF_MONTH), 12,0, 0);
		final String date = new SimpleDateFormat(DEFUALT_TIME_PATTEN).format(g.getTime());
		
		final GregorianCalendar g2 = new GregorianCalendar(calendar.get(Calendar.YEAR), 
				calendar.get(Calendar.MONTH)+1,calendar.get(Calendar.DAY_OF_MONTH), 11,59, 59);
		final String date2 = new SimpleDateFormat(DEFUALT_TIME_PATTEN).format(g2.getTime());
		
		return new String[] { date, date2 };
	}
	
	/**
	 * 本周
	 * @return
	 */
	public static String[] currWeek() {
		final Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.DAY_OF_WEEK, 1);
	
		final GregorianCalendar g = new GregorianCalendar(calendar.get(Calendar.YEAR), 
				calendar.get(Calendar.MONTH),calendar.get(Calendar.DAY_OF_MONTH), 12,0, 0);
		final String date = new SimpleDateFormat(DEFUALT_TIME_PATTEN).format(g.getTime());
		
		
		final GregorianCalendar g2 = new GregorianCalendar(calendar.get(Calendar.YEAR), 
				calendar.get(Calendar.MONTH),calendar.get(Calendar.DAY_OF_MONTH)+7, 11,59, 59);
		final String date2 = new SimpleDateFormat(DEFUALT_TIME_PATTEN).format(g2.getTime());
		
		return new String[] { date, date2 };
	}
	
	/**
	 * 上一周第一天
	 * @return
	 */
	public static String lastWeekStart() {
		int weeks = 0;
		weeks--;
		final int mondayPlus = getMondayPlus();
		final GregorianCalendar currentDate = new GregorianCalendar();
		currentDate.add(GregorianCalendar.DATE, mondayPlus + weeks-7);
		currentDate.set(currentDate.get(GregorianCalendar.YEAR), 
				currentDate.get(GregorianCalendar.MONTH), currentDate.get(GregorianCalendar.DAY_OF_MONTH), 11, 59, 59);
		final String date = new SimpleDateFormat(DEFUALT_TIME_PATTEN).format(currentDate.getTime());
		
		return date;
	}
	
	/**
	 * 上一周最后一天
	 * @return
	 */
	public static String lastWeekEnd() {
		int weeks = 0;
		weeks--;
		final int mondayPlus = getMondayPlus();
		final GregorianCalendar currentDate = new GregorianCalendar();
		currentDate.add(GregorianCalendar.DATE, mondayPlus + weeks);
		currentDate.set(currentDate.get(GregorianCalendar.YEAR), 
				currentDate.get(GregorianCalendar.MONTH), currentDate.get(GregorianCalendar.DAY_OF_MONTH), 12, 0, 0);
		final String date = new SimpleDateFormat(DEFUALT_TIME_PATTEN).format(currentDate.getTime());
		
		return date;
	}
	
	public static int getMondayPlus() {
		final Calendar cd = Calendar.getInstance();
		int dayOfWeek = cd.get(Calendar.DAY_OF_WEEK)-1;
		if (dayOfWeek == 1) {
			return 0;
		} else {
			return 1 - dayOfWeek;
		}
	}
	
	/**
	 * 获取到昨天这个时候
	 * @return            long 类型的时间
	 */
	public static Long getYesterday(){
		final Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR, -12);
        cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTimeInMillis();
	}
	
	/**
	 * 时间字符串转换成时间对象
	 * @param strTime         字符串时间
	 * @return                @see Date
	 */
	public static Date string2Time(String strTime) {
		final SimpleDateFormat format = new SimpleDateFormat(DEFUALT_TIME_PATTEN);
		try {
			return format.parse(strTime);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 时间字符串转换成时间对象(long类型)
	 * @param strTime          字符串时间
	 * @return                 long 类型的时间
	 */
	public static long string2TimeLong(String strTime) {
		final Date date = string2Time(strTime);
		return date == null ? 0l : date.getTime(); 
	}
	
	/**
	 * 时间(long类型)转换成时间字符串
	 * @param time             long 类型时间
	 * @return                 字符串时间
	 */
	public static String time2String(long time) {
		final Date date = new Date(time);
		final SimpleDateFormat format = new SimpleDateFormat(DEFUALT_TIME_PATTEN);
		return format.format(date);
	}
	
	/**
	 * 时间类型转换成时间字符串
	 * @param date            @see Date
	 * @return                字符串时间
	 */
	public static String time2String(Date date) {
		final SimpleDateFormat format = new SimpleDateFormat(DEFUALT_TIME_PATTEN);
		return format.format(date);
	}
	
	public static void main(String[] args) {
		System.out.println(time2String(1389801600000l));
	}
}
